package com.kaibes.core.base.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.function.ToLongFunction;

import com.kaibes.core.base.function.ToIntegerFunction;

public class ListUtils {

    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Object obj) {
        return obj == null || (obj instanceof List && ((List)obj).isEmpty());
    }
    
    public static boolean isEmpty(Collection<?> list) {
        return list == null || list.isEmpty();
    }

    public static boolean isNotEmpty(List<?> list) {
        return list != null && !list.isEmpty();
    }
    
    public static boolean nullOrContains(List<?> list, Object value) {
        return list == null || list.contains(value);
    }
    
    public static boolean nullOrNotContains(List<?> list, Object value) {
        return list == null || !list.contains(value);
    }

    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(Collection<T> list) {
        if (isEmpty(list)) {
            return null;
        }
        try {
            T obj = list.iterator().next();
            T[] array = (T[]) Array.newInstance(obj.getClass(), 0);
            array = list.toArray(array);
            return array;
        } catch (NoSuchElementException  e) {
            return null;
        }
    }

    public static <T> List<Long> toLong(List<T> list, ToLongFunction<T> mapper) {
        List<Long> longList = new ArrayList<Long>();
        list.forEach(t -> longList.add(mapper.applyAsLong(t)));
        return longList;
    }
    
    public static <T> List<Integer> toInteger(List<T> list, ToIntegerFunction<T> mapper) {
        List<Integer> integerList = new ArrayList<Integer>();
        list.forEach(t -> integerList.add(mapper.applyAsInteger(t)));
        return integerList;
    }

    public static <T> List<T> deepCopy(List<T> list) {
        try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();ObjectOutputStream out = new ObjectOutputStream(byteOut)) {
            out.writeObject(list);
            try (ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());ObjectInputStream in = new ObjectInputStream(byteIn);) {
                @SuppressWarnings("unchecked")
                List<T> dest = (List<T>) in.readObject();
                return dest;
            } catch (IOException | ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
